﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace MeTool
{
    public static class StringHelper
    {
        /// <summary>
        /// 将已有字符串填充为规定长度，如果已有字符串超过这个长度则返回这个字符串
        /// </summary>
        /// <param name="str">被填充的字符串</param>
        /// <param name="filledChar">填充的字符</param>
        /// <param name="len">填充后的长度</param>
        /// <param name="isPre">是否填充在前</param>
        /// <returns></returns>
        public static string Fill(this string str, char filledChar, int len, bool isPre)
        {
            if (str == null || str.Length >= len) return str;
            var dfill = new string(filledChar, len - str.Length);
            return isPre ? dfill + str : str + dfill;
        }

        /// <summary>
        /// 将已有字符串填充为规定长度，如果已有字符串超过这个长度则返回这个字符串 字符填充于字符串前
        /// </summary>
        /// <param name="str">被填充的字符串</param>
        /// <param name="filledChar">填充的字符</param>
        /// <param name="len">填充后的长度</param>
        /// <returns></returns>
        public static string FillBefore(this string str, char filledChar, int len)
        {
            return Fill(str, filledChar, len, true);
        }

        /// <summary>
        /// 将已有字符串填充为规定长度，如果已有字符串超过这个长度则返回这个字符串 字符填充于字符串后
        /// </summary>
        /// <param name="str">被填充的字符串</param>
        /// <param name="filledChar">填充的字符</param>
        /// <param name="len">填充后的长度</param>
        /// <returns></returns>
        public static string FillAfter(this string str, char filledChar, int len)
        {
            return Fill(str, filledChar, len, false);
        }

        /// <summary>
        /// 此字符串为 null 或者不包含任何字符时返回true
        /// <para>为 null 时返回 true 不会报错</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsEmpty(this string str)
        {
            return str == null || str.Length == 0;
        }

        /// <summary>
        /// 此字符串实例包含字符时返回true
        /// <para>为 null 时返回 false 不会报错</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNotEmpty(this string str)
        {
            return str != null && str.Length > 0;
        }

        /// <summary>
        /// 是否包含空字符串。
        /// <para>如果指定的字符串数组的长度为 0，或者其中的任意一个元素是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="strs"></param>
        /// <returns></returns>
        public static bool HasEmpty(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (IsEmpty(item)) return true;
            return false;
        }

        /// <summary>
        /// 指定字符串数组中的元素，是否全部为空字符串。
        /// <para>如果指定的字符串数组的长度为 0，或者所有元素都是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="strs"></param>
        /// <returns></returns>
        public static bool IsAllEmpty(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (!IsEmpty(item)) return false;
            return true;
        }

        /// <summary>
        /// 指定字符串数组中的元素，是否都不为空字符串。
        /// <para>如果指定的字符串数组的长度不为 0，或者所有元素都不是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static bool IsAllNotEmpty(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (!IsNotEmpty(item)) return false;
            return true;
        }

        /// <summary>
        /// 指定字符串数组中的元素，是否不为空字符串。
        /// <para>如果指定的字符串数组的长度为 0，或者其中的任意一个元素不是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static bool HasNotEmpty(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (IsNotEmpty(item)) return true;
            return false;
        }

        /// <summary>
        /// 如果对象是空白返回true，空白的定义如下：
        ///<para>1. null _ _ 2. 空字符串："" _ _ 3. 空格、全角空格、制表符、换行符，等不可见字符</para>
        ///<para>例：</para>
        ///<para>StrUtil.isBlankIfStr(null) // true</para>
        ///<para>StrUtil.isBlankIfStr("") // true</para>
        ///<para>StrUtil.isBlankIfStr(" \t\n") // true</para>
        ///<para>StrUtil.isBlankIfStr("abc") // false</para>
        ///<para>注意：该方法与 IsEmpty(Object) 的区别是： 该方法会校验空白字符，且性能相对于 IsEmpty(Object) 略慢。</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsBlank(this string str)
        {
            if (str == null || str == "") return true;
            return mRegexIsBlankAll.IsMatch(str);
        }
        private readonly static Regex mRegexIsBlankAll = new Regex(@"^\s+$");

        /// <summary>
        /// 如果指定字符是空白字符, 则返回True. 空白字符的定义如下:
        ///<para>1. null _ _ 2. 空字符串："" _ _ 3. 空格、全角空格、制表符、换行符，等不可见字符</para>
        /// </summary>
        /// <param name="chr"></param>
        /// <returns></returns>
        public static bool IsBlankChar(this char chr)
        {
            return mRegexHasBlank.IsMatch(chr.ToString());
        }
        private readonly static Regex mRegexHasBlank = new Regex(@"\s");

        /// <summary>
        /// 字符串是否为非空白，非空白的定义如下：
        ///<para>— 1. 不为 null。 — 2. 不为空字符串：""。 — 3. 不为空格、全角空格、制表符、换行符，等不可见字符</para> 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNotBlank(this string str)
        {
            return !IsBlank(str);
        }

        /// <summary>
        /// 指定字符串数组中，是否包含空字符串。
        /// <para>如果指定的字符串数组的长度为 0，或者其中的任意一个元素是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="strs"></param>
        /// <returns></returns>
        public static bool HasBlank(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (IsBlank(item)) return true;
            return false;
        }

        /// <summary>
        /// 指定字符串数组中，是否存在不为 null 或空对象或空白符的对象。
        /// <para>如果指定的字符串数组的长度为 0，或者其中的任意一个元素不是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="strs"></param>
        /// <returns></returns>
        public static bool HasNotBlank(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (!IsBlank(item)) return true;
            return false;
        }

        /// <summary>
        /// 指定字符串数组中的元素，是否全部为空字符串。
        /// <para>如果指定的字符串数组的长度为 0，或者所有元素都是空字符串，则返回 true。</para>
        /// </summary>
        /// <param name="strs"></param>
        /// <returns></returns>
        public static bool IsAllBlank(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (!IsBlank(item)) return false;
            return true;
        }

        /// <summary>
        /// 是否全都不为 null 或空对象或空白符的对象
        /// <para></para>
        /// </summary>
        /// <param name="args">如果指定的字符串数组的长度为 0，或者所有元素都不是空字符串，则返回 true。</param>
        /// <returns></returns>
        public static bool IsAllNotBlank(this string[] strs)
        {
            if (strs == null || strs.Length == 0) return true;
            foreach (var item in strs) if (IsBlank(item)) return false;
            return true;
        }

        /// <summary>
        /// 给定字符串是否包含空白符（空白符包括空格、制表符、全角空格和不间断空格）
        /// <para>如果给定字符串为 null 或者 ""，则返回 false</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool ContainsBlank(this string str)
        {
            if (str == null || str == "") return false;
            return mRegexHasBlank.IsMatch(str);
        }

        /// <summary>
        /// 将byte数组解码为字符串, 默认为Utf8格式
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ToStr(this byte[] bytes, Encoding encoding = null)
        {
            if (bytes == null) return null;
            if (encoding == null) encoding = Encoding.UTF8;
            return encoding.GetString(bytes);
        }

        /// <summary>
        /// 创建StringBuilder对象
        /// </summary>
        /// <param name="capacity">初始大小</param>
        /// <returns></returns>
        public static StringBuilder Builder(int capacity)
        {
            return new StringBuilder(capacity);
        }

        /// <summary>
        /// 获得StringReader
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static StringReader GetReader(this string str)
        {
            return new StringReader(str);
        }

        /// <summary>
        /// 获得StringWriter
        /// </summary>
        /// <returns></returns>
        public static StringWriter GetWriter()
        {
            return new StringWriter();
        }

        /// <summary>
        /// 返回反转的字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ReverseStr(this string str)
        {
            var value = str.Reverse();
            return new string(value.ToArray());
        }

        /// <summary>
        /// 比较2个字符串的相似度（使用余弦相似度）
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns>0-1之间的数</returns>
        public static double SimilarityCos(string str1, string str2)
        {
            str1 = str1.Trim();
            str2 = str2.Trim();
            if (string.IsNullOrEmpty(str1) || string.IsNullOrEmpty(str2))
                return 0;

            List<string> lstr1 = SimpParticiple(str1);
            List<string> lstr2 = SimpParticiple(str2);
            //求并集
            var strUnion = lstr1.Union(lstr2);
            //求向量
            List<int> int1 = new List<int>();
            List<int> int2 = new List<int>();
            foreach (var item in strUnion)
            {
                int1.Add(lstr1.Count(o => o == item));
                int2.Add(lstr2.Count(o => o == item));
            }

            double s = 0;
            double den1 = 0;
            double den2 = 0;
            for (int i = 0; i < int1.Count(); i++)
            {
                //求分子
                s += int1[i] * int2[i];
                //求分母（1）
                den1 += Math.Pow(int1[i], 0);
                //求分母（2）
                den2 += Math.Pow(int2[i], 0);
            }

            return s / (Math.Sqrt(den1) * Math.Sqrt(den2));
        }

        /// <summary>
        /// 简单分词（需要更好的效果，需要这里优化，比如把：【今天天气很好】，分成【今天，天气，很好】，同时可以做同义词优化，【今天】=【今日】效果更好）
        /// </summary>
        private static List<string> SimpParticiple(string str)
        {
            List<string> vs = new List<string>();
            foreach (var item in str)
            {
                vs.Add(item.ToString());
            }
            return vs;
        }

        /// <summary>
        /// 获取两个字符串的相似度
        /// </summary>
        /// <param name="sourceString">第一个字符串</param>
        /// <param name="str">第二个字符串</param>
        /// <returns></returns>
        public static decimal SimilarityWith(this string sourceString, string str)
        {

            decimal Kq = 2;
            decimal Kr = 1;
            decimal Ks = 1;

            char[] ss = sourceString.ToCharArray();
            char[] st = str.ToCharArray();

            //获取交集数量
            int q = ss.Intersect(st).Count();
            int s = ss.Length - q;
            int r = st.Length - q;

            return Kq * q / (Kq * q + Kr * r + Ks * s);
        }

        /// <summary>
        /// 当给定字符串为空字符串时，转换为null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string EmptyToNull(this string str)
        {
            return IsEmpty(str) ? null : str;
        }

        /// <summary>
        /// 检查字符串是否为 null、“null”、“undefined”
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNullOrUndefined(this string str)
        {
            return str == null || str == "null" || str == "undefined";
        }

        /// <summary>
        /// 检查字符串是否为 null、“”、“null”、“undefined”
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsEmptyOrUndefined(this string str)
        {
            return str == null || str == "" || str == "null" || str == "undefined";
        }

        /// <summary>
        /// 检查字符串是否为 null、空白串、“null”、“undefined”
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsBlankOrUndefined(this string str)
        {
            return IsBlank(str) || str == "null" || str == "undefined";
        }

        /// <summary>
        /// 除去字符串头尾部的空白，如果字符串是 null，依然返回 null。
        /// <para>注意：和 string.Trim() 不同，此方法使用IsBlankChar(char) 来判定空白， 因而可以除去英文字符集之外的其它空白，如中文空格。</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimStr(this string str)
        {
            if (str == null) return null;
            var dStart = 0;
            for (var xx = 0; xx < str.Length; xx++)
            {
                if (IsBlankChar(str[xx])) dStart = xx + 1; else break;
            }
            if (dStart == str.Length - 1) return "";
            var dEnd = str.Length;
            for (var xx = str.Length - 1; xx >= 0; xx--)
            {
                if (IsBlankChar(str[xx])) dEnd = xx; else break;
            }
            return str.Substring(dStart, dEnd - dStart);
        }

        /// <summary>
        /// 除去字符串头尾部的空白，如果字符串是null，返回""。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimStrToEmpty(this string str)
        {
            if (str == null) return "";
            return TrimStr(str);
        }

        /// <summary>
        /// 除去字符串头尾部的空白，如果字符串是null或者""，返回null。
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimStrToNull(this string str)
        {
            if (IsEmpty(str)) return null;
            return TrimStr(str);
        }

        /// <summary>
        /// 除去字符串头部的空白，如果字符串是null，则返回null。
        /// <para>注意，和String.trim()不同，此方法使用 IsBlankChar(char) 来判定空白， 因而可以除去英文字符集之外的其它空白，如中文空格。</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimStrStart(this string str)
        {
            if (str == null) return null;
            var dStart = -1;
            for (var xx = 0; xx < str.Length; xx++)
            {
                if (IsBlankChar(str[xx])) dStart = xx + 1; else break;
            }
            if (dStart == str.Length - 1) return "";
            return str.Substring(dStart);
        }

        /// <summary>
        /// 除去字符串尾部的空白，如果字符串是null，则返回null。
        /// <para>注意，和String.trim()不同，此方法使用 IsBlankChar(char) 来判定空白， 因而可以除去英文字符集之外的其它空白，如中文空格。</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string TrimStrEnd(this string str)
        {
            if (str == null) return null;
            var dEnd = str.Length;
            for (var xx = str.Length - 1; xx >= 0; xx--)
            {
                if (IsBlankChar(str[xx])) dEnd = xx; else break;
            }
            return str.Substring(0, dEnd);
        }

        /// <summary>
        /// 指定范围内查找字符串，忽略大小写
        /// </summary>
        /// <param name="str"></param>
        /// <param name="searchStr"></param>
        /// <returns></returns>
        public static int IndexOfIgnoreCase(this string str, string searchStr)
        {
            if (str == null || str == "" || searchStr == null || searchStr == "") return -1;
            return str.IndexOf(searchStr, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 指定范围内查找字符串，忽略大小写
        /// </summary>
        /// <param name="str"></param>
        /// <param name="searchStr"></param>
        /// <returns></returns>
        public static int LastIndexOfIgnoreCase(this string str, string searchStr)
        {
            if (str == null || str == "" || searchStr == null || searchStr == "") return -1;
            return str.LastIndexOf(searchStr, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 去掉指定前缀
        /// <para>若前缀不是 preffix， 返回原字符串</para>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string RemovePrefix(this string str, string prefix)
        {
            if (str == null || prefix == null || prefix == "") return str;
            return str.StartsWith(prefix) ? str.Substring(prefix.Length) : str;
        }

        /// <summary>
        /// 忽略大小写去掉指定前缀
        /// <para>若前缀不是 prefix， 返回原字符串</para>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string RemovePrefixIgnoreCase(this string str, string prefix)
        {
            if (str == null || prefix == null || prefix == "") return str;
            return str.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) ? str.Substring(prefix.Length) : str;
        }

        /// <summary>
        /// 去掉指定后缀
        /// <para>切掉后的字符串，若后缀不是 suffix， 返回原字符串</para>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public static string RemoveSuffix(this string str, string suffix)
        {
            if (str == null || suffix == null || suffix == "") return str;
            return str.EndsWith(suffix) ? str.Substring(0, str.Length - suffix.Length) : str;
        }

        /// <summary>
        /// 忽略大小写去掉指定后缀
        /// <para>若后缀不是 suffix， 返回原字符串</para>
        /// </summary>
        /// <param name="str"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public static string RemoveSuffixIgnoreCase(this string str, string suffix)
        {
            if (str == null || suffix == null || suffix == "") return str;
            return str.EndsWith(suffix, StringComparison.OrdinalIgnoreCase) ? str.Substring(0, str.Length - suffix.Length) : str;
        }

        /// <summary>
        /// 清理空白字符
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string CleanBlank(this string str)
        {
            if (str == null) return null;
            return mRegexHasBlank.Replace(str, "");
        }

        /// <summary>
        /// 去除两边的指定字符串
        /// </summary>
        /// <param name="str">被处理的字符串</param>
        /// <param name="prefix">前缀</param>
        /// <param name="suffix">后缀</param>
        /// <returns></returns>
        public static string Strip(this string str, string prefix, string suffix)
        {
            if (str == null) return null;
            if (prefix != null && str.StartsWith(prefix)) str = str.Substring(prefix.Length);
            if (suffix != null && str.EndsWith(suffix)) str = str.Substring(0, str.Length - suffix.Length);
            return str;
        }

        /// <summary>
        /// 去除两边的指定字符串，忽略大小写
        /// </summary>
        /// <param name="str">被处理的字符串</param>
        /// <param name="prefix">前缀</param>
        /// <param name="suffix">后缀</param>
        /// <returns></returns>
        public static string StripIgnoreCase(this string str, string prefix, string suffix)
        {
            if (str == null) return null;
            if (prefix != null && str.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) str = str.Substring(prefix.Length);
            if (suffix != null && str.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) str = str.Substring(0, str.Length - suffix.Length);
            return str;
        }

        /// <summary>
        /// 如果给定字符串不是以prefix开头的，在开头补充 prefix
        /// </summary>
        /// <param name="str"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string SetPrefix(this string str, string prefix)
        {
            if (str == null) return prefix;
            if (prefix == null || prefix == "") return str;
            return str.StartsWith(prefix) ? str : prefix + str;
        }

        /// <summary>
        /// 如果给定字符串不是以prefix开头的，在开头补充 prefix，忽略大小写
        /// </summary>
        /// <param name="str"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        public static string SetPrefixIgnoreCase(this string str, string prefix)
        {
            if (str == null) return prefix;
            if (prefix == null || prefix == "") return str;
            return str.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) ? str : prefix + str;
        }

        /// <summary>
        /// 如果给定字符串不是以suffix结尾的，在尾部补充 suffix
        /// </summary>
        /// <param name="str"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public static string SetSuffix(this string str, string suffix)
        {
            if (str == null) return suffix;
            if (suffix == null || suffix == "") return str;
            return str.EndsWith(suffix) ? str : str + suffix;
        }

        /// <summary>
        /// 如果给定字符串不是以suffix结尾的，在尾部补充 suffix，忽略大小写
        /// </summary>
        /// <param name="str"></param>
        /// <param name="suffix"></param>
        /// <returns></returns>
        public static string SetSuffixIgnoreCase(this string str, string suffix)
        {
            if (str == null) return suffix;
            if (suffix == null || suffix == "") return str;
            return str.EndsWith(suffix, StringComparison.OrdinalIgnoreCase) ? str : str + suffix;
        }

        /// <summary>
        /// 编码字符串，编码为UTF-8
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] ToUTF8Bytes(this string str)
        {
            return Encoding.UTF8.GetBytes(str);
        }

        /// <summary>
        /// 编码字符串, 默认为UTF-8
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte[] ToBytes(this string str, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            return encoding.GetBytes(str);
        }

        /// <summary>
        /// 返回给定文本的字节长度 ( 长度按单字节 = 1 , 双字节 = 2 计算 )
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int GBKLength(this string str)
        {
            return Encoding.Default.GetByteCount(str);
        }

        /// <summary>
        /// 把字符串修剪成指定字节长。 不足时后补空格，超出时截断 ( 字节长度按单字节 = 1 , 双字节 = 2 计算 )
        /// </summary>
        /// <param name="str"></param>
        /// <param name="gbkLength"></param>
        /// <param name="manyIsDot"></param>
        /// <returns></returns>
        public static string CorrectGBK(this string str, int gbkLength, bool manyIsDot = false)
        {
            var dGBKLength = GBKLength(str);
            if (gbkLength <= 0)
            {
                return "";
            }
            else if (gbkLength == 1)
            {
                return dGBKLength == 1 ? str : " ";
            }
            else if (gbkLength == 2)
            {
                switch (dGBKLength)
                {
                    case 0:
                        return "  ";
                    case 1:
                        return str + " ";
                    case 2:
                        return str;
                    default:
                        return manyIsDot ? "…" : "  ";
                }
            }
            else if (dGBKLength <= gbkLength)
            {
                return str + new string(' ', gbkLength - dGBKLength);
            }
            else
            {
                string dDot = "";
                if (manyIsDot)
                {
                    gbkLength -= 2;
                    dDot = "…";
                }
                if (str.Length > gbkLength)
                {
                    str = str.Substring(0, gbkLength);
                }
                while (GBKLength(str) > gbkLength)
                {
                    str = str.Substring(0, str.Length - 1);
                }
                return str + new string(' ', gbkLength - GBKLength(str)) + dDot;
            }
        }

        /// <summary>
        /// 把字符串修剪成指定字节长。 不足时前补空格，超出时前部截断 ( 字节长度按单字节 = 1 , 双字节 = 2 计算 )
        /// </summary>
        /// <param name="str"></param>
        /// <param name="gbkLength"></param>
        /// <param name="manyIsDot"></param>
        /// <returns></returns>
        public static string CorrectGBKRight(this string str, int gbkLength, bool manyIsDot = false)
        {
            var dGBKLength = GBKLength(str);
            if (gbkLength <= 0)
            {
                return "";
            }
            else if (gbkLength == 1)
            {
                return dGBKLength == 1 ? str : " ";
            }
            else if (gbkLength == 2)
            {
                switch (dGBKLength)
                {
                    case 0:
                        return "  ";
                    case 1:
                        return " " + str;
                    case 2:
                        return str;
                    default:
                        return manyIsDot ? "…" : "  ";
                }
            }
            else if (dGBKLength <= gbkLength)
            {
                return new string(' ', gbkLength - dGBKLength) + str;
            }
            else
            {
                string dDot = "";
                if (manyIsDot)
                {
                    gbkLength -= 2;
                    dDot = "…";
                }
                if (str.Length > gbkLength)
                {
                    str = str.Substring(str.Length - gbkLength);
                }
                while (GBKLength(str) > gbkLength)
                {
                    str = str.Substring(1);
                }
                return dDot + new string(' ', gbkLength - GBKLength(str)) + str;
            }
        }

        /// <summary>
        /// 整理文本,把一段文本整理成指定字节长度并居中 ( 字节长度按单字节 = 1 , 双字节 = 2 计算 )
        /// </summary>
        /// <param name="str"></param>
        /// <param name="gbkLength"></param>
        /// <param name="manyIsDot"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string CorrectGBKCenter(string str, int gbkLength, bool manyIsDot = false)
        {
            var dGBKLength = GBKLength(str);
            if (dGBKLength <= gbkLength)
            {
                //当文本长度比需要的长度小时,在左面附加半数空格,并在右边补齐
                str = new string(' ', (gbkLength - dGBKLength) / 2) + str;
                return str + new string(' ', gbkLength - GBKLength(str));
            }
            //当文本长度大于需要长度时
            if (manyIsDot)
            {
                //当需要附加省略号时
                do
                {
                    str = str.Substring(0, str.Length - 1);
                }
                while (GBKLength(str) + 2 > gbkLength);
                return str + new string(' ', gbkLength - GBKLength(str) - 2) + "…";
            }
            //不附加省略号
            do
            {
                str = str.Substring(0, str.Length - 1);
            }
            while (GBKLength(str) > gbkLength);
            return str + new string(' ', gbkLength - GBKLength(str));
        }

        /// <summary>
        /// 替换指定字符串的指定区间内字符为"*" 俗称：脱敏功能
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="startInclude">开始位置（包含）</param>
        /// <param name="endExclude">结束位置（不包含）</param>
        /// <returns></returns>
        public static string Hide(this string str, int startInclude, int endExclude)
        {
            if (str == null) return null;
            if (startInclude < 0) startInclude = 0;
            if (startInclude > str.Length) startInclude = str.Length - 1;
            if (endExclude < 0) endExclude = 0;
            if (endExclude > str.Length) endExclude = str.Length - 1;
            if (startInclude >= endExclude) return "";
            return str.Substring(0, startInclude) + new string('*', endExclude - startInclude) + str.Substring(endExclude);
        }

        /// <summary>
        /// 返回从左算起指定长度的部分文本
        /// </summary>
        /// <param name="str"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string Left(this string str, int length)
        {
            return str.Substring(0, length);
        }

        /// <summary>
        /// 返回从右算起指定长度的部分文本
        /// </summary>
        /// <param name="str"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string Right(this string str, int length)
        {
            return str.Substring(str.Length - length);
        }

        /// <summary>
        /// 此文本可以转换为数字时, 返回 True ( 文本中仅包含 0 ~ 9 )
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNumeric(this string str)
        {
            if (str == null || str == "") return false;
            foreach (var item in str) if (item < '0' || item > '9') return false;

            return true;
        }

        /// <summary>
        /// 此文本可以转换为 double 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsDouble(this string str)
        {
            if (str == null || str == "") return false;
            return double.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 double ,不能转换时返回 0 (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static double ToDouble(this string str)
        {
            if (str == null || str == "") return 0;
            return double.TryParse(str, out var dValue) ? dValue : 0;
        }

        /// <summary>
        /// 此文本可以转换为 decimal 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsDecimal(this string str)
        {
            if (str == null || str == "") return false;
            return decimal.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 decimal ,不能转换时返回 0 (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal ToDecimal(this string str)
        {
            if (str == null || str == "") return 0;
            return decimal.TryParse(str, out var dValue) ? dValue : 0;
        }

        /// <summary>
        /// 此文本可以转换为 int 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsInteger(this string str)
        {
            if (str == null || str == "") return false;
            return int.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 int ,不能转换时返回 0 (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int ToInteger(this string str)
        {
            if (str == null || str == "") return 0;
            return int.TryParse(str, out var dValue) ? dValue : 0;
        }

        /// <summary>
        /// 此文本可以转换为 long 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsLong(this string str)
        {
            if (str == null || str == "") return false;
            return long.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 long ,不能转换时返回 0 (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static long ToLong(this string str)
        {
            if (str == null || str == "") return 0;
            return long.TryParse(str, out var dValue) ? dValue : 0;
        }

        /// <summary>
        /// 此文本可以转换为 DateTime 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsDateTime(this string str)
        {
            if (str == null || str == "") return false;
            return DateTime.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 DateTime ,不能转换时返回 2000-01-01 (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str)
        {
            if (str == null || str == "") return new DateTime(2000, 1, 1);
            return DateTime.TryParse(str, out var dValue) ? dValue : new DateTime(2000, 1, 1);
        }

        /// <summary>
        /// 此文本可以转换为 Guid 时,返回True
        /// <para>注意: 当 str 为 null 或为空时, 将返回 True</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsGuid(this string str)
        {
            if (str == null || str == "") return true;
            return Guid.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 long ,不能转换时返回 Guid.Empty (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static Guid ToGuid(this string str)
        {
            if (str == null || str == "") return Guid.Empty;
            return Guid.TryParse(str, out var dValue) ? dValue : Guid.Empty;
        }

        /// <summary>
        /// 此文本可以转换为 bool 时,返回True
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsBoolean(this string str)
        {
            if (str == null || str == "") return false;
            if (str == "1" || str == "0") return true;
            return bool.TryParse(str, out var _);
        }

        /// <summary>
        /// 把此文本转换为 bool ,不能转换时返回 false (不抛出异常)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool ToBoolean(this string str)
        {
            if (str == null || str == "") return false;
            if (str == "1") return true;
            if (str == "0") return false;
            return bool.TryParse(str, out var dValue) && dValue;
        }
    }
}